
#define STACKSIZE 10000

typedef struct{
    int di;
    float df;
    //int type; // 0: int 1: float 2: boolean
    int tipo;       
}DATA;

typedef struct{
  int position;
  DATA Datos[STACKSIZE];
}STACKOPERATIONS;

typedef struct{
  int position;
  int items [STACKSIZE];
}STACKRETURN;

//se indexa con el id de la letra que es un numero
typedef struct{
  int PosSp;   //Posicion del ultimo stackpointer en sp
  int sp[STACKSIZE];   //Inicio de cada espacio
  int maximo[STACKSIZE];        //valor maximo de cada espacio
  DATA Datos[STACKSIZE];     //Tipos y valores de cada varable
  int position;              //tamano del vector Datos
  int ocupado[STACKSIZE];    // 1 ocupado 0 desocupado
}STACKVARIABLES;

//Pilas
STACKOPERATIONS PilaOper;
STACKRETURN PilaRetornos;
STACKVARIABLES PilaVarables;

int error;

//Imprime el tipo de error segun el tipo
void Error(int tipo)
{
	 error=1;
     if(tipo==0)
     {
         // printf("Stack Overflow.\n");
		  //exit(1);
     }
     else if(tipo==1)
     {
          //printf("Stack Underflow.\n");
		  //exit(1);
     }
     else if(tipo==2)
     {
          //printf("error: el id no existe\n");
          //exit(1);
     }
     else if(tipo==3)
     {
          //printf("error\n");
          //exit(0);
     }
     else
     {
          //printf("error, isnt desconocida\n");
          //exit(1);
     }
}

void push_Pila_Oper(DATA dato)
{
	if(PilaOper.position == STACKSIZE)
        Error(0);
	PilaOper.Datos[PilaOper.position++] = dato;
}

DATA pop_Pila_Oper()
{
	if(PilaOper.position == 0) 
        Error(1);
	
	return PilaOper.Datos[--PilaOper.position];
}

void Clear_Pila_Oper()
{
     while(PilaOper.position!=0)
     {
         pop_Pila_Oper();
     }
}

void push_Pila_Retornos(int value)
{
	if(PilaRetornos.position == STACKSIZE) 
        Error(0);
	PilaRetornos.items[PilaRetornos.position++] = value;
}

int pop_Pila_Retornos()
{
	if(PilaRetornos.position == 0) 
        Error(1);
	return PilaRetornos.items[--PilaRetornos.position];
}

void Add_Variable_PilaVarables(int id,DATA dato)
{
	if(PilaVarables.position == STACKSIZE)
        Error(0);
	int pp=PilaVarables.sp[PilaVarables.PosSp]+id;
	PilaVarables.Datos[pp] = dato;
	PilaVarables.ocupado[pp]=1;
	if(PilaVarables.maximo[PilaVarables.PosSp]<id)	
        PilaVarables.maximo[PilaVarables.PosSp]=id;
    PilaVarables.position++;   
	
}

void push_Pila_PilaVarables()
{
	if(PilaVarables.position == STACKSIZE || PilaVarables.PosSp == STACKSIZE)
         Error(0);
	int pp=PilaVarables.maximo[PilaVarables.PosSp];
	int spp=PilaVarables.sp[PilaVarables.PosSp];
	PilaVarables.PosSp++;
	PilaVarables.sp[PilaVarables.PosSp]=spp+pp+1;
	PilaVarables.maximo[PilaVarables.PosSp]=0;
}

void pop_Pila_PilaVarables()
{
	if(PilaVarables.position == 0 || PilaVarables.PosSp == 0) 
         Error(1);
	int inicio=PilaVarables.sp[PilaVarables.PosSp];
    int fin=inicio+PilaVarables.maximo[PilaVarables.PosSp];
    int i=0;
    for(i=inicio;i<=fin;i++)
    {
        if(PilaVarables.ocupado[i]==1)
            PilaVarables.position--;
        PilaVarables.ocupado[i]=0;  
    }
        
	PilaVarables.maximo[PilaVarables.PosSp]=0;
	PilaVarables.PosSp--;
}


int Buscar_Variable_en_Pila_Variables(int id)
{
    
    int d=PilaVarables.ocupado[PilaVarables.sp[PilaVarables.PosSp]+id];
    if(d==1)
        return 1;           
    else          
        return 0;
}

DATA get_valor_Pila_Variables(int id)
{
	DATA d;
     if (Buscar_Variable_en_Pila_Variables(id)==1)
     {
         d=PilaVarables.Datos[PilaVarables.sp[PilaVarables.PosSp]+id];
         return d;
     }
     else
         Error(2);
     return d;
}


